/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.gpsmgr;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javolution.util.FastList;
import javolution.util.FastMap;
import net.sf.json.JSONObject;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityJoinOperator;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.util.EntityFindOptions;
import org.ofbiz.entity.util.EntityUtil;

public class GPSManagerEvents {
    public static final String module = GPSManagerEvents.class.getName();
    public static final String resourceError = "ProductErrorUiLabels";
    
    // Please note : the structure of map in this function is according to the JSON data map of the jsTree
    @SuppressWarnings("unchecked")
    public static void getChildTree(HttpServletRequest request, HttpServletResponse response){
        Delegator delegator = (Delegator) request.getAttribute("delegator");
        String partyId = request.getParameter("partyId");
        String onclickFunctionGPSOwner = request.getParameter("onclickFunctionGPSOwner");
        String onclickFunctionGPS = request.getParameter("onclickFunctionGPS");
        String hrefStringGPSOwner = request.getParameter("hrefStringGPSOwner");
        String hrefStringGPS = request.getParameter("hrefStringGPS");
        
        List partyList = FastList.newInstance();
        List<GenericValue> partyRelationships;
        //check party roll up
        try {
            GenericValue party = delegator.findOne("Party" ,UtilMisc.toMap("partyId", partyId), false);
            if (UtilValidate.isNotEmpty(party)) {
                partyRelationships = EntityUtil.filterByDate(delegator.findByAnd("PartyRelationship", UtilMisc.toMap(
                        "partyIdFrom", party.get("partyId"), "partyRelationshipTypeId", "GROUP_ROLLUP"), null, false));
                if (UtilValidate.isNotEmpty(partyRelationships)) {
                    for (GenericValue partyRelationship : partyRelationships ) {
                        String partyIdTo = null;
                        String partyName = null;
                        String title = null;
                        
                        Map josonMap = FastMap.newInstance();
                        Map dataMap = FastMap.newInstance();
                        Map dataAttrMap = FastMap.newInstance();
                        Map attrMap = FastMap.newInstance();
                        
                        partyIdTo = partyRelationship.getString("partyIdTo");
                        
                        //Party or Sub Party
                        GenericValue partyNameView = delegator.findOne("PartyNameView" ,UtilMisc.toMap("partyId", partyId), false);
                        if (UtilValidate.isNotEmpty(partyNameView)) {
                            String firstName = (String) partyNameView.get("firstName");
                            String lastName = (String) partyNameView.get("lastName");
                            String groupName = (String) partyNameView.get("groupName");
                            title = (firstName != null ? firstName : "") + (firstName != null ? " " : "") + (lastName != null ? lastName : "") +
                                    (groupName != null ? groupName : "");
                            List<GenericValue> productRoleList = EntityUtil.filterByDate(delegator.findByAnd("ProductRole", UtilMisc.toMap(
                                    "partyId", partyId, "roleTypeId", "PRODUCT_OWNER"), null, false));
                            title = title + "(" + productRoleList.size() +"/" + getAllProducts(delegator, partyId) +")";
                            josonMap.put("title", title);
                        }
                        //Check child existing
                        List<GenericValue> subPartyRelationships = EntityUtil.filterByDate(delegator.findByAnd("PartyRelationship", UtilMisc.toMap(
                                "partyIdFrom", partyIdTo, "partyRelationshipTypeId", "GROUP_ROLLUP"), null, false));
                        
                        List<GenericValue> subProductRoles = EntityUtil.filterByDate(delegator.findByAnd("ProductRole", UtilMisc.toMap(
                                "partyId", partyIdTo, "roleTypeId", "PRODUCT_OWNER"), null, false));
                        
                        //check Sub PartyRelationship
                        //if (UtilValidate.isNotEmpty(subPartyRelationships) || UtilValidate.isNotEmpty(subProductRoles)) {
                        if (UtilValidate.isNotEmpty(subPartyRelationships)) {
                            josonMap.put("state", "closed");
                        }
                        
                        //Sub Party
                        partyNameView = delegator.findOne("PartyNameView" ,UtilMisc.toMap("partyId", partyIdTo), false);
                        if (UtilValidate.isNotEmpty(partyNameView)) {
                            String firstName = (String) partyNameView.get("firstName");
                            String lastName = (String) partyNameView.get("lastName");
                            String groupName = (String) partyNameView.get("groupName");
                            title = (firstName != null ? firstName : "") + (firstName != null ? " " : "") + (lastName != null ? lastName : "") +
                                    (groupName != null ? groupName : "");
                            List<GenericValue> productRoleList = EntityUtil.filterByDate(delegator.findByAnd("ProductRole", UtilMisc.toMap(
                                    "partyId", partyIdTo, "roleTypeId", "PRODUCT_OWNER"), null, false));
                            title = title + "(" + productRoleList.size() +"/" + getAllProducts(delegator, partyIdTo) +")";
                        }
                        
                        dataAttrMap.put("onClick", onclickFunctionGPSOwner + "('" + partyIdTo + "')");
                        
                        String hrefStr = hrefStringGPSOwner + partyIdTo;
                        
                        dataAttrMap.put("href", hrefStr);
                        
                        dataMap.put("attr", dataAttrMap);
                        
                        attrMap.put("rel", "Y");
                        attrMap.put("id", partyIdTo);
                        josonMap.put("attr", attrMap);
                        dataMap.put("title", title);
                        josonMap.put("data", dataMap);
                        
                        partyList.add(josonMap);
                    }
                    
                }
                // Get ProductRole
                /***
                Set<String> fieldsToSelect = UtilMisc.toSet("productId");
                List<String> orderBy = UtilMisc.toList("productId");
                EntityFindOptions findOptions = new EntityFindOptions();
                findOptions.setDistinct(true);
                List<EntityCondition> conditionList = FastList.newInstance();
                List<EntityCondition> conditionOrList = FastList.newInstance();
                
                conditionList.add(EntityCondition.makeCondition("roleTypeId", EntityOperator.EQUALS, "PRODUCT_OWNER"));
                conditionList.add(EntityCondition.makeCondition("partyId", EntityOperator.EQUALS, partyId));
                
                conditionOrList.add(EntityCondition.makeCondition("thruDate", EntityOperator.EQUALS, null));
                conditionOrList.add(EntityCondition.makeCondition("thruDate", EntityOperator.GREATER_THAN, UtilDateTime.nowTimestamp()));
                
                conditionList.add(EntityCondition.makeCondition(conditionOrList, EntityJoinOperator.OR));
                EntityCondition entityCondition = EntityCondition.makeCondition(conditionList);
                
                List<GenericValue> productRoles = delegator.findList("ProductRole", entityCondition, fieldsToSelect, orderBy, findOptions, false);
                if (UtilValidate.isNotEmpty(productRoles)) {
                    for (GenericValue productRole : productRoles) {
                        String productId = null;
                        String partyName = null;
                        String title = null;
                        
                        Map josonMap = FastMap.newInstance();
                        Map dataMap = FastMap.newInstance();
                        Map dataAttrMap = FastMap.newInstance();
                        Map attrMap = FastMap.newInstance();
                        
                        productId = productRole.getString("productId");
                        
                        //Party or Sub Party
                        GenericValue partyNameView = delegator.findOne("PartyNameView" ,UtilMisc.toMap("partyId", partyId), false);
                        if (UtilValidate.isNotEmpty(partyNameView)) {
                            partyName = (String) partyNameView.get("groupName");
                            josonMap.put("title", partyName);
                        }
                        
                        //josonMap.put("state", "closed");
                        
                        //Product
                        GenericValue productContext = delegator.findOne("Product" ,UtilMisc.toMap("productId", productId), false);
                        if (UtilValidate.isNotEmpty(productContext)) {
                            title = productContext.getString("internalName");
                        }
                        
                        dataAttrMap.put("onClick", onclickFunctionGPS + "('" + productId + "')");
                        
                        String hrefStr = hrefStringGPS + productId;
                        dataAttrMap.put("href", hrefStr);
                        
                        dataMap.put("attr", dataAttrMap);
                        
                        attrMap.put("rel", "P");
                        attrMap.put("id", productId);
                        josonMap.put("attr", attrMap);
                        dataMap.put("title", title);
                        josonMap.put("data", dataMap);
                        
                        partyList.add(josonMap);
                    }
                }
                ***/
                toJsonObjectList(partyList,response);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @SuppressWarnings("unchecked")
    public static void toJsonObjectList(List attrList, HttpServletResponse response){
        String jsonStr = "[";
        for (Object attrMap : attrList) {
            JSONObject json = JSONObject.fromObject(attrMap);
            jsonStr = jsonStr + json.toString() + ',';
        }
        jsonStr = jsonStr + "{ } ]";
        if (UtilValidate.isEmpty(jsonStr)) {
            Debug.logError("JSON Object was empty; fatal error!",module);
        }
        // set the X-JSON content type
        response.setContentType("application/json");
        // jsonStr.length is not reliable for unicode characters
        try {
            response.setContentLength(jsonStr.getBytes("UTF8").length);
        } catch (UnsupportedEncodingException e) {
            Debug.logError("Problems with Json encoding",module);
        }
        // return the JSON String
        Writer out;
        try {
            out = response.getWriter();
            out.write(jsonStr);
            out.flush();
        } catch (IOException e) {
            Debug.logError("Unable to get response writer",module);
        }
    }
    public static int getAllProducts(Delegator delegator, String partyId) {
        int allGps = 0;
        try {
            List<GenericValue> productRoleList = delegator.findByAnd("ProductRole", UtilMisc.toMap("partyId",partyId, "roleTypeId" ,"PRODUCT_OWNER"), null , false);
            productRoleList = EntityUtil.filterByDate(productRoleList);
        
            allGps = productRoleList.size();
            List<GenericValue> partyRelationshipList;
            partyRelationshipList = delegator.findByAnd("PartyRelationship", UtilMisc.toMap("partyIdFrom", partyId), null, false);
            partyRelationshipList = EntityUtil.filterByDate(partyRelationshipList);
            if (UtilValidate.isNotEmpty(partyRelationshipList)) {
                for (GenericValue partyRelationship : partyRelationshipList) {
                    allGps = allGps + getAllProducts(delegator, partyRelationship.getString("partyIdTo"));
                }
            }
        } catch (GenericEntityException e) {
        }
        return allGps;
    }
    public static List<String> getAllProductIds(Delegator delegator, String partyId) {
        List<String> productIds = FastList.newInstance();
        try {
            List<GenericValue> productRoleList = delegator.findByAnd("ProductRole", UtilMisc.toMap("partyId",partyId, "roleTypeId" ,"PRODUCT_OWNER"), null , false);
            productRoleList = EntityUtil.filterByDate(productRoleList);
        
            for(GenericValue productRole : productRoleList) {
                productIds.add(productRole.getString("productId"));
            }
            List<GenericValue> partyRelationshipList;
            partyRelationshipList = delegator.findByAnd("PartyRelationship", UtilMisc.toMap("partyIdFrom", partyId), null, false);
            partyRelationshipList = EntityUtil.filterByDate(partyRelationshipList);
            if (UtilValidate.isNotEmpty(partyRelationshipList)) {
                for (GenericValue partyRelationship : partyRelationshipList) {
                    productIds.addAll(getAllProductIds(delegator, partyRelationship.getString("partyIdTo")));
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        return productIds;
    }
}
